
package com.x52im.rbchat.logic.search.content;

import android.view.View;
import android.view.ViewGroup;

import com.eva.android.widget.WidgetUtils;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

/**
 * 可搜索内容描述对象实现类。
 *
 * @param <R> 列表item对应的数据对象引用
 * @param <V> 对应的ViewHoler对象子类
 * @author Jack Jiang
 * @since 8.2
 */
public abstract class SearchableContent<R extends Object, V extends RecyclerView.ViewHolder> {

    /** 在列表中本搜索内容对应的默认最多显示item条数 */
    public final static int RESULT_LIST_ITEM_DEFAULT_SHOW_COUNT = 3;//4;

    /** 当前搜索的关键词 */
    protected String currentKeyword = null;
    /**
     * 是否显示所有搜索结果（true表示是，否则搜索结果列表界面中将按常量{@link #RESULT_LIST_ITEM_DEFAULT_SHOW_COUNT}
     * 定义的数量只显示有限数量的结果）。
     */
    protected boolean showAllResult = false;

    /**
     * 用于RecycleView的adapter中的onCreateViewHolder方法。
     *
     * @param fragment 对应的fragment对象应用
     * @param parent   对应于列表item的view对象应用
     * @param viewType 列表item的viewType
     * @return 返回对应的ViewHoler对象子类
     */
    public abstract V onCreateViewHolder(Fragment fragment, @NonNull ViewGroup parent, int viewType);

    /**
     * 用于RecycleView的adapter中的onBindViewHolder方法。
     *
     * @param fragment   对应的fragment对象应用
     * @param holder     对应的ViewHoler对象子类
     * @param r          列表item对应的数据对象引用
     * @param showCatlog 是否显示item上方的标题文本（true表示显示，否则不显示）
     */
    public abstract void onBind(Fragment fragment, V holder, R r, boolean showCatlog);

    /**
     * 点击事件处理。
     *
     * @param fragment 所在fragment对象引用
     * @param holder   viewHodler对象引用
     * @param view     列表item的view对象引用
     * @param r        列表item对应的数据对象引用
     * @see #doClickImpl(Fragment, RecyclerView.ViewHolder, View, Object)
     */
    public final void doClick(Fragment fragment, V holder, View view, R r) {
        WidgetUtils.hideInputMethod(fragment.getActivity(), view);
        doClickImpl(fragment, holder, view, r);
    }

    /**
     * 点击"查看更多"事件处理。
     *
     * @param fragment 所在fragment对象引用
     * @param view     列表item的view对象引用
     * @see #doClickMoreImpl(Fragment, View)
     */
    public final void doClickMore(Fragment fragment, View view) {
        WidgetUtils.hideInputMethod(fragment.getActivity(), view);
        doClickMoreImpl(fragment, view);
    }

    /**
     * 点击事件真正的实施方法。子类可重写本方法实现自已的逻辑。
     *
     * @param fragment 所在fragment对象引用
     * @param holder   viewHodler对象引用
     * @param view     列表item的view对象引用
     * @param r        列表item对应的数据对象引用
     */
    public abstract void doClickImpl(Fragment fragment, V holder, View view, R r);

    /**
     * 点击"查看更多"事件真正的实施方法。子类可重写本方法实现自已的逻辑。
     *
     * @param fragment 所在fragment对象引用
     * @param view     列表item的view对象引用
     * @see #doClickMore(Fragment, View)
     */
    public abstract void doClickMoreImpl(Fragment fragment, View view);

    /**
     * 开始搜索。
     *
     * @param keyword 要搜索的关键词
     * @return 返回的搜索结果集
     * @see #doSearchImpl(String)
     */
    public final List<R> doSearch(String keyword, boolean searchAll) {
        this.currentKeyword = keyword;
        return doSearchImpl(keyword, searchAll);
    }

    /**
     * 搜索实施方法。
     *
     * @param keyword 要搜索的关键词
     * @return 返回的搜索结果集
     */
    public abstract List<R> doSearchImpl(String keyword, boolean searchAll);

    /**
     * 返回本搜索内容显示在结果列表界面中时的对应的viewType。
     * 子类重写本方法实现自已的viewType生成逻辑，要求是：本值应大于100（100以内为保留值）、且本值应在显示列表中全局唯一。
     *
     * @return 返回viewType值
     */
    public abstract int getViewType();

    /**
     * 返回对应搜索内容的标题栏文本内容。
     *
     * @return 返回标题栏文本内容
     */
    public abstract String getCategory();

    /**
     * 是否显示所有搜索结果。
     *
     * @return true表示是，否则搜索结果列表界面中将按常量{@link #RESULT_LIST_ITEM_DEFAULT_SHOW_COUNT}定义的数量只显示有限数量的结果
     */
    public boolean isShowAllResult() {
        return showAllResult;
    }

    /**
     * 设置是否显示所有搜索结果。
     *
     * @param showAllResult true表示是，否则搜索结果列表界面中将按常量{@link #RESULT_LIST_ITEM_DEFAULT_SHOW_COUNT}定义的数量只显示有限数量的结果
     */
    public SearchableContent<R, V> setShowAllResult(boolean showAllResult) {
        this.showAllResult = showAllResult;
        return this;
    }
}
